using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.Profile;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using Commerce.Common;
using Commerce.Providers;
using Commerce.PayPal;

namespace CommerceForUmbraco.usercontrols
{
    public partial class Checkout : System.Web.UI.UserControl
    {
        // the user profile - address, email, shipping, tax
        protected ProfileBase profile;
        // the current order - for shipping and tax calcs
        protected Order currentOrder = null;
        // for Address Validation - via the AV Provider
        UpsAddressValidateProvider validate = new UpsAddressValidateProvider();
        AddressValidateCollection collection = null;

        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                if (!IsPostBack)
                {
                    string qs = HttpContext.Current.Request.QueryString.ToString();
                    string redirectPage = "";

                    // redirect to configured checkoutUrl
                    // unless it's running on a specified test server or localhost
                    if ((!HttpContext.Current.Request.Url.ToString().Contains(Utility.GetTestHostName()))
                        && (!HttpContext.Current.Request.Url.ToString().Contains("localhost")))
                    {
                        //  set to checkout URL as defined in web.config
                        int removeStart = Context.Request.Url.AbsoluteUri.IndexOf('&');
                        string compareUrl = "";

                        if (removeStart > 0)
                            compareUrl = Context.Request.Url.AbsoluteUri.Remove(removeStart);
                        else
                            compareUrl = Context.Request.Url.AbsoluteUri;

                        string[] requestPage = compareUrl.Split('/');
                        string[] configPage = Utility.GetCheckoutUrl().Split('/');

                        if (requestPage[requestPage.Length - 1] != configPage[configPage.Length - 1])
                        {
                            redirectPage = Utility.GetCheckoutUrl() + "?" + qs;
                            Response.Redirect(redirectPage);
                        }
                    }
                        
                    // hide the shipping and complete buttons if this is the first time we're here
                    shippingContinue.Visible = false;
                    completeCheckout.Visible = false;
                    //step2.Visible = false;
                    //step3.Visible = false;

                    // check the URL for a token from PayPal using Express Checkout
                    if (Utility.GetParameter("token") != string.Empty)
                    {
                        //get the info from PayPal about this buyer
                        ProcessExpressReturn(Utility.GetParameter("token"));

                        // load the PayPal complete button, display addresses
                        shippingContinue.Visible = true;
                        completeCheckout.Visible = false;
                        //step2.Visible = false;
                        //step3.Visible = true;

                        ShipAddressEntry addBoxShip = (ShipAddressEntry)shipAddressEntry;
                         if (addBoxShip != null)
                         {
                             addBoxShip.SelectedAddress = (Address)profile.GetPropertyValue("LastShippingAddress");
                             // get the shipping options if we have a shipping address
                             if (addBoxShip.SelectedAddress.Zip.Length > 0)
                             {
                                 SetCurrentOrder();
                                 BindShipping(LoadPackage());

                                 // update the order display to reflect default shipping and tax
                                 currentOrder.ShippingAmount = decimal.Parse(radShipChoices.SelectedValue);
                                 currentOrder.ShippingMethod = radShipChoices.SelectedItem.Text;

                                 // set tax amount in profile
                                 profile.SetPropertyValue("CurrentOrderTax", GetCurrentOrderTax());
                                 // also set tax for the currentOrder
                                 currentOrder.TaxAmount = GetCurrentOrderTax();
                             }
                         }

                         // show the address entry boxes
                         addressPanel.Visible = true;
                         shippingPanel.Visible = true;
                        // disable the address boxes for edits
                         DisableTextBoxEdit(shipAddressEntry);
                        // display the 'complete checkout' link
                         completeCheckout.Visible = true;
                         ppCheckoutlabel.Visible = true;
                         // hide the email continue link
                         emailContinue.Visible = false;
                         shippingContinue.Visible = false;
                         paymentBox.Visible = false;
                         paymentTypeList.Enabled = false;
                        // hide the Billing Address input
                         billAddressEntry.Visible = false;
                         //dpBillingText.Visible = false;
                        // display the 'Address on file with PayPal' text
                         ppBillingText.Visible = true;
                    }
                }

                // get the order and set the order display
                SetCurrentOrder();
                lblOrderItems.Text = currentOrder.mcOrderItemsTable();
                orderRunningTotal.Text = currentOrder.OrderTotal.ToString("c");

            }
            catch (Exception ex)
            {
                message.Text = "We're sorry, an error occured.<br />" + ex.Message;
            }

        }

        #region button handlers

        protected void emailContinue_Click(object sender, EventArgs e)
        {
            // either send to PayPal or continue with on-site payment
            try
            {
                // encode the user provided email address - used to create new members
                string encEmail = HttpUtility.HtmlEncode(Email.Text);
                // set up the order
                SetCurrentOrder();

                // verify one option was selected
                if (paymentTypeList.SelectedIndex == -1)
                    throw new Exception("Please select a payment type before continuing.");

                if (paymentTypeList.SelectedValue == "pp")
                {
                    SetExpressCheckout();
                }
                else
                {
                    // look for account - 
                    // if found, display address and payment box
                    // and populate with profile address

                    SetProfile(Email.Text);

                    MembershipUserCollection mUC = Membership.FindUsersByName(Email.Text);
                    if (mUC.Count != 0)
                    {
                        ShipAddressEntry addBoxShip = (ShipAddressEntry)shipAddressEntry;
                        if ((addBoxShip != null) && (profile.GetPropertyValue("LastShippingAddress") != null))
                        {
                            addBoxShip.SelectedAddress = (Address)profile.GetPropertyValue("LastShippingAddress");

                            // get the shipping options if we have a shipping address
                            if (addBoxShip.SelectedAddress.Zip.Length > 0)
                            {
                                //SetCurrentOrder();
                                BindShipping(LoadPackage());

                                // update the order display to reflect default shipping and tax
                                currentOrder.ShippingAmount = decimal.Parse(radShipChoices.SelectedValue);
                                currentOrder.ShippingMethod = radShipChoices.SelectedItem.Text;

                                // set tax amount in profile
                                profile.SetPropertyValue("CurrentOrderTax", GetCurrentOrderTax());
                                // also set tax for the currentOrder
                                currentOrder.TaxAmount = GetCurrentOrderTax();

                                lblOrderItems.Text = currentOrder.mcOrderItemsTable();
                                orderRunningTotal.Text = currentOrder.OrderTotal.ToString("c");
                            }
                        }

                        // set to billing address if we have it, otherwise set to the shipping address
                        BillAddressEntry addBoxBill = (BillAddressEntry)billAddressEntry;
                        if (addBoxBill != null)
                        {
                            Address billAdd = (Address)profile.GetPropertyValue("LastBillingAddress");
                            if (billAdd.StateOrRegion.Length == 0)
                            {
                                addBoxBill.SelectedAddress = (Address)profile.GetPropertyValue("LastShippingAddress");
                            }
                            else
                            {
                                addBoxBill.SelectedAddress = (Address)profile.GetPropertyValue("LastBillingAddress");
                            }
                        }
                    }
                    else
                    {
                        //create a new member with the supplied email and temporary password
                        string pwd = Membership.GeneratePassword(8, 1);
                        Membership.CreateUser(encEmail, pwd, encEmail);
                        // TODO:  display the generated password
                    }

                    // update the order with the current user name
                    currentOrder.UserName = encEmail;
                    
                    // copy down the email address / user name to the address boxes
                    shipAddressEntry.Email = Email.Text;
                    billAddressEntry.Email = Email.Text;

                    // display the address entry boxes
                    addressPanel.Visible = true;
                    // hide the email continue link
                    emailContinue.Visible = false;

                    // set the paymentType list to read only
                    paymentTypeList.Enabled = false;

                    shippingContinue.Visible = true;

                }

            }
            catch (Exception ex)
            {
                message.Text = "We're sorry, an error occured.<br />" + ex.Message;        
            }
        }

        protected void shippingContinue_Click(object sender, EventArgs e)
        {
            try
            {
                // if the address has an exact match then don't show the dialog
                if (this.showModal())
                {

                SaveAddresses();

                // set billing address if we have it, otherwise set to the shipping address
                BillAddressEntry addBoxBill = (BillAddressEntry)billAddressEntry;
                if (addBoxBill != null)
                {
                    Address billAdd = (Address)profile.GetPropertyValue("LastBillingAddress");
                    if (billAdd.Zip.Length == 0)
                    {
                        addBoxBill.SelectedAddress = (Address)profile.GetPropertyValue("LastShippingAddress");
                    }
                    else
                    {
                        addBoxBill.SelectedAddress = (Address)profile.GetPropertyValue("LastBillingAddress");
                    }
                }

                    // see if we have all required fields
                    Page.Validate();

                    if (Page.IsValid)
                    {
                        // save the address data to the UserProfie
                        SaveAddresses();

                        // calculate shipping based on shipping address and packaging
                        SetCurrentOrder();
                        BindShipping(LoadPackage());

                        // set the selected shipping method and cost and then
                        //   update the order display to reflect default shipping and tax
                        currentOrder.ShippingAmount = decimal.Parse(radShipChoices.SelectedValue);
                        currentOrder.ShippingMethod = radShipChoices.SelectedItem.Text;

                        // set tax amount in profile
                        profile.SetPropertyValue("CurrentOrderTax", GetCurrentOrderTax());
                        // also set tax for th currentOrder
                        currentOrder.TaxAmount = GetCurrentOrderTax();

                        lblOrderItems.Text = currentOrder.mcOrderItemsTable();
                        orderRunningTotal.Text = currentOrder.OrderTotal.ToString("c");

                        // display the shipping and payment boxes
                        shippingPanel.Visible = true;

                        // hide the address continue link
                        shippingContinue.Visible = false;

                        completeCheckout.Visible = true;
                        //step3.Visible = true;
                    }
                }
            }
            catch (Exception)
            {
                // catch all exceptions and put up error display
                message.Text = "There is a problem with the address entered.  Please check that you provided a 2-character state code and the correct Zip Code.";
            }
        }

        protected void completeCheckout_Click(object sender, EventArgs e)
        {
            string transactionID = "";

            try
            {
                // save the address data to the profile - for convenience
                SaveAddresses();

                SetOrderInfo();
                SetCurrentOrder();
                MembershipUser mUser = Membership.GetUser(Email.Text);

                // update the order with the current user name if not set, or is different
                if (mUser != null)
                {
                    if (mUser.UserName != currentOrder.UserName)
                        currentOrder.UserName = mUser.UserName;

                }

                // force page validation before we process the order
                Page.Validate();

                if (Page.IsValid)
                {
                    if (Request.QueryString["token"] != null)
                    {
                        // PayPal ExpressCheckout - DoExpressCheckout
                        transactionID = RunExpressCheckout();
                    }
                    else
                    {
                        // process the payment - its a CC direct pay
                        transactionID = RunCharge();
                    }

                    // here's where you might put your integration logic for a fullfillment system
                    if (bool.Parse(ConfigurationManager.AppSettings.Get("useIntegrator")))
                    {
                        // here's where we populate the Integration Address table
                        SaveIntegrationAdress();
                    }

                    //if an error occurred, the transactionId will be null or empty. 
                    if (!String.IsNullOrEmpty(transactionID))
                    {

                        radShipChoices.Enabled = false;
                        inputPanel.Visible = false;
                        receiptPanel.Visible = true;

                        // display the receipt
                        PackageInfo package = LoadPackage();
                        if (currentOrder.ShippingAddress != null && currentOrder.BillingAddress != null)
                        {
                            BindShipping(package);
                        }

                        // set up reciept
                        lblReceiptAddress.Text = receiptAddress();
                        result.Text = currentOrder.OrderNumber.ToString();
                        lblOrderItems.Text = currentOrder.mcOrderItemsTable();
                        receiptDisplay.Text = currentOrder.mcOrderItemsTable();

                        // hide the checkout complete link to avoid duplicate orders
                        completeCheckout.Visible = false;
                    }
                }

            }
            catch (Exception ex)
            {
                //Response.Write(ex.Message + ex.StackTrace);
                message.Text = "We're sorry, an error occured.<br />" + ex.Message;
            }
        }

        // modal popup SELECT THIS button
        protected void Button2_Click(object sender, EventArgs e)
        {
            // use selected values
            ModalPopupExtender1.Hide();

            // make sure a value was selected
            if (RadioButtonList1.SelectedValue != string.Empty)
            {
                int useIndex = int.Parse(RadioButtonList1.SelectedValue) - 1;

                if (collection == null)
                    collection = validate.CheckAddress(shipAddressEntry.SelectedAddress);

                TextBox stateBox = (TextBox)shipAddressEntry.FindControl("stateCode");
                stateBox.Text = collection[useIndex].state;
                TextBox cityBox = (TextBox)shipAddressEntry.FindControl("txtCity");
                cityBox.Text = collection[useIndex].city;
                TextBox zipBox = (TextBox)shipAddressEntry.FindControl("txtZip");
                zipBox.Text = collection[useIndex].zipLow.ToString();
            }

        }

        // modal popup CANCEL button
        protected void Button3_Click(object sender, EventArgs e)
        {
            // let the user update the entries manually
            ModalPopupExtender1.Hide();
        }

        protected void LinkButton1_Click(object sender, EventArgs e)
        {
            showModal();
        }

        protected void radShipChoices_SelectedIndexChanged(object sender, EventArgs e)
        {
            //set the Profile Shipping Bits
            SetProfile(Email.Text);
            profile.SetPropertyValue("CurrentOrderShipping", decimal.Parse(radShipChoices.SelectedValue));
            profile.SetPropertyValue("CurrentOrderShippingMethod", radShipChoices.SelectedItem.Text);

            SetOrderInfo();  

            // update the order display
            lblOrderItems.Text = currentOrder.mcOrderItemsTable();
            orderRunningTotal.Text = currentOrder.OrderTotal.ToString("c");
        }

        #endregion

        #region checkout utility methods

        void SetOrderInfo()
        {
            if (radShipChoices != null && radShipChoices.Items.Count > 0)
            {
                currentOrder.ShippingAmount = decimal.Parse(radShipChoices.SelectedValue);
                currentOrder.ShippingMethod = radShipChoices.SelectedItem.Text;
            }

            currentOrder.ShippingAddress = (Address)profile.GetPropertyValue("LastShippingAddress");
            currentOrder.BillingAddress = (Address)profile.GetPropertyValue("LastBillingAddress");

            // save the addresses as HTML strings for ERP integration
            currentOrder.ShipToAddress = shipAddressEntry.SelectedAddress.ToHtmlString();
            currentOrder.BillToAddress = billAddressEntry.SelectedAddress.ToHtmlString();

            // get tax
            currentOrder.TaxAmount = GetCurrentOrderTax();

            //pull the CC info from the PaymentBox
            currentOrder.CreditCardNumber = paymentBox.CCNumber;
            currentOrder.CreditCardExpireMonth = paymentBox.ExpirationMonth;
            currentOrder.CreditCardExpireYear = paymentBox.ExpirationYear;
            currentOrder.CreditCardSecurityNumber = paymentBox.SecurityCode;
            currentOrder.CreditCardType = paymentBox.CCType;

            if (currentOrder.BillingAddress != null)
            {
                currentOrder.FirstName = currentOrder.BillingAddress.FirstName;
                currentOrder.LastName = currentOrder.BillingAddress.LastName;
                currentOrder.Email = currentOrder.BillingAddress.Email;
            }

        }

        public void SetCurrentOrder()
        {
            if (currentOrder == null)
                currentOrder = OrderController.GetCurrentOrder();
        }

        public void SetProfile(string userName)
        {
            // set the profile as authenticated
            if (profile == null)
                profile = ProfileBase.Create(userName, true);
        }

        /// <summary>
        /// Saves the order address to the integration adress table
        /// </summary>
        protected void SaveIntegrationAdress()
        {
            IntegrationAddress shipping = null;
            IntegrationAddress billing = null;

            // check to see if we have records for this order already
            // SHIPPING
            int shipExistsCount = new SubSonic.Query(IntegrationAddress.Schema)
                .AddWhere(IntegrationAddress.Columns.AddressType, "SHIP")
                .AddWhere(IntegrationAddress.Columns.OrderId, currentOrder.OrderID.ToString()).GetCount("orderId");

            if (shipExistsCount > 0)
            {
                // update shipAddress
                string addressId = new SubSonic.Select(IntegrationAddress.Columns.AddressId)
                    .From(IntegrationAddress.Schema)
                    .WhereExpression(IntegrationAddress.Columns.AddressType).IsEqualTo("SHIP")
                    .And(IntegrationAddress.Columns.OrderId).IsEqualTo(currentOrder.OrderID.ToString())
                    .ExecuteScalar<string>();

                shipping = new IntegrationAddress(addressId);
            }
            else
            {
                shipping = new IntegrationAddress();
            }
            // BILLING
            int billExistsCount = new SubSonic.Query(IntegrationAddress.Schema)
                .AddWhere(IntegrationAddress.Columns.AddressType, "BILL")
                .AddWhere(IntegrationAddress.Columns.OrderId, currentOrder.OrderID.ToString()).GetCount("orderId");

            if (billExistsCount > 0)
            {
                // update shipAddress
                string addressId = new SubSonic.Select(IntegrationAddress.Columns.AddressId)
                    .From(IntegrationAddress.Schema)
                    .WhereExpression(IntegrationAddress.Columns.AddressType).IsEqualTo("BILL")
                    .And(IntegrationAddress.Columns.OrderId).IsEqualTo(currentOrder.OrderID.ToString())
                    .ExecuteScalar<string>();

                billing = new IntegrationAddress(addressId);
            }
            else
            {
                billing = new IntegrationAddress();
            }

            try
            {

                shipping.AddressType = "SHIP";
                shipping.OrderId = currentOrder.OrderID;
                shipping.FirstName = shipAddressEntry.SelectedAddress.FirstName;
                shipping.LastName = shipAddressEntry.SelectedAddress.LastName;
                shipping.Email = shipAddressEntry.SelectedAddress.Email;
                shipping.Address1 = TrimData(shipAddressEntry.SelectedAddress.Address1, 40);
                shipping.Address2 = TrimData(shipAddressEntry.SelectedAddress.Address2, 40);
                shipping.City = TrimData(shipAddressEntry.SelectedAddress.City, 25);
                shipping.Country = TrimData(shipAddressEntry.SelectedAddress.Country, 3);
                shipping.State = TrimData(shipAddressEntry.SelectedAddress.StateOrRegion, 3);
                shipping.Zip = TrimData(shipAddressEntry.SelectedAddress.Zip, 12);
                shipping.Phone = "0"; // TrimData(shipAddressEntry.SelectedAddress.Phone, 25);

                shipping.Save("checkout");

                billing.AddressType = "BILL";
                billing.OrderId = currentOrder.OrderID;
                billing.FirstName = billAddressEntry.SelectedAddress.FirstName;
                billing.LastName = billAddressEntry.SelectedAddress.LastName;
                billing.Email = billAddressEntry.SelectedAddress.Email;
                billing.Address1 = TrimData(billAddressEntry.SelectedAddress.Address1, 40);
                billing.Address2 = TrimData(billAddressEntry.SelectedAddress.Address2, 40);
                billing.City = TrimData(billAddressEntry.SelectedAddress.City, 25);
                billing.Country = TrimData(billAddressEntry.SelectedAddress.Country, 3);
                billing.State = TrimData(billAddressEntry.SelectedAddress.StateOrRegion, 3);
                billing.Zip = TrimData(billAddressEntry.SelectedAddress.Zip, 12);
                billing.Phone = "0";  // TrimData(billAddressEntry.SelectedAddress.Phone, 25);

                billing.Save("checkout");

            }
            catch (Exception ex)
            {
                // swallow the error for now - we've already processed the order
                message.Text = "Your order was successfully placed but we're sorry, an error occured.<br />" + ex.Message;
            }

        }

        protected string TrimData(string data, int length)
        {
            int totalLength = data.Length;

            if (totalLength > length)
            {
                return data.Substring(0, length);
            }
            else
            {
                return data;
            }
        }

        void SaveAddresses()
        {
            // saves the entered address to the user profile
            SetProfile(Email.Text);

            Address saveAdd = new Address();

            saveAdd.FirstName = shipAddressEntry.SelectedAddress.FirstName;
            saveAdd.LastName = shipAddressEntry.SelectedAddress.LastName;
            saveAdd.Email = shipAddressEntry.SelectedAddress.Email;
            saveAdd.Address1 = shipAddressEntry.SelectedAddress.Address1;
            saveAdd.Address2 = shipAddressEntry.SelectedAddress.Address2;
            saveAdd.City = shipAddressEntry.SelectedAddress.City;
            saveAdd.Country = shipAddressEntry.SelectedAddress.Country;
            saveAdd.StateOrRegion = shipAddressEntry.SelectedAddress.StateOrRegion;
            saveAdd.Zip = shipAddressEntry.SelectedAddress.Zip;
            saveAdd.Phone = shipAddressEntry.SelectedAddress.Phone;
            profile.SetPropertyValue("LastShippingAddress", saveAdd);

            Address saveBillAdd = new Address();

            saveBillAdd.FirstName = billAddressEntry.SelectedAddress.FirstName;
            saveBillAdd.LastName = billAddressEntry.SelectedAddress.LastName;
            saveBillAdd.Email = billAddressEntry.SelectedAddress.Email;
            saveBillAdd.Address1 = billAddressEntry.SelectedAddress.Address1;
            saveBillAdd.Address2 = billAddressEntry.SelectedAddress.Address2;
            saveBillAdd.City = billAddressEntry.SelectedAddress.City;
            saveBillAdd.Country = billAddressEntry.SelectedAddress.Country;
            saveBillAdd.StateOrRegion = billAddressEntry.SelectedAddress.StateOrRegion;
            saveBillAdd.Zip = billAddressEntry.SelectedAddress.Zip;
            saveBillAdd.Phone = billAddressEntry.SelectedAddress.Phone;

            // also set the PayPal specifics - not sure why these are in Address
            saveBillAdd.PayPalPayerID = Request.QueryString.Get("PayerID");
            saveBillAdd.PayPalToken = Request.QueryString.Get("token");

            profile.SetPropertyValue("LastBillingAddress", saveBillAdd);

            profile.Save();
        }

        string RunCharge()
        {
            string sOut = "";

            try
            {

                Transaction trans = OrderController.TransactOrder(currentOrder, TransactionType.CreditCardPayment);
                //the orderID is set during the TransactOrder process
                sOut = currentOrder.OrderGUID;

            }
            catch (Exception)
            {
                // let fall through since the empty sOut will be logged up the stack
            }

            return sOut;
        }

        PackageInfo LoadPackage()
        {
            //Create shipping package
            SiteConfig.Load();

            PackageInfo package = new PackageInfo();
            package.FromZip = SiteConfig.ShipFromZip;
            package.FromCountryCode = SiteConfig.ShipFromCountryCode;

            Address shipAdd = (Address)profile.GetPropertyValue("LastShippingAddress");
            package.ToZip = shipAdd.Zip;
            package.ToCountryCode = shipAdd.Country;

            package.Weight = currentOrder.GetItemsWeight();
            package.Width = Convert.ToInt16(currentOrder.GetTotalWidth());
            package.Height = Convert.ToInt16(currentOrder.GetTotalHeight());
            package.Length = Convert.ToInt16(currentOrder.GetMaxLength());
            package.DimensionUnit = SiteConfig.DimensionUnit;
            package.PackagingBuffer = SiteConfig.ShipPackagingBuffer;

            //Create Dictionary args for future expansion options
            //package.Args = new Dictionary<string, string>();
            return package;

        }

        void BindShipping(PackageInfo package)
        {
            // send the order amount and number of units
            int numberUnits = 0;
            foreach (OrderItem i in currentOrder.Items)
            {
                numberUnits += i.Quantity;
            }

            Commerce.Providers.DeliveryOptionCollection options =
                Commerce.Providers.FulfillmentService.GetOptions
                (package, (currentOrder.OrderTotal - currentOrder.ShippingAmount), numberUnits);

            radShipChoices.DataSource = options;
            radShipChoices.DataTextField = "Service";
            radShipChoices.DataValueField = "Rate";
            radShipChoices.DataBind();

            foreach (DeliveryOption d in options)
            {
                if (d.Service.Contains("Free Shipping"))
                {
                    // select Free Shipping is it's an option
                    radShipChoices.SelectedValue = d.Rate.ToString();
                    break;
                }
                else if (d.Service.Contains("Flat Rate"))
                {
                    // select Flat Rate Shipping is it's an option
                    radShipChoices.SelectedValue = d.Rate.ToString();
                    break;
                }
                else
                {
                    // otherwise select the first in the list
                    radShipChoices.SelectedIndex = 0;
                }
            }

            //localize it using the C formatter for local currency
            decimal dRate = 0;
            foreach (ListItem l in radShipChoices.Items)
            {
                dRate = decimal.Parse(l.Value);
                l.Text += ": " + dRate.ToString("C");
            }

            //set the Profile Shipping Bits
            profile.SetPropertyValue("CurrentOrderShipping", decimal.Parse(radShipChoices.SelectedValue));
            profile.SetPropertyValue("CurrentOrderShippingMethod", radShipChoices.SelectedItem.Text);
        }

        protected string receiptAddress()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("<table><tr><th>Shipping Address:</th><th>Billing Address:</th></tr><tr><td>");
            sb.Append(shipAddressEntry.SelectedAddress.mcOrderAddressTable());          
            sb.Append("</td><td>");
            sb.Append(billAddressEntry.SelectedAddress.mcOrderAddressTable());
            sb.Append("</td></tr></table>");

            return sb.ToString();
        }

        protected decimal GetCurrentOrderTax()
        {
            decimal dTax = 0;
            Address shipAdd = (Address)profile.GetPropertyValue("LastShippingAddress");
            // PVS - 5/23/2008- change to use tax calc by state rather than ZIP
            USState state = (USState)Utility.StringToEnum(typeof(Commerce.Common.USState), shipAdd.StateOrRegion);

            dTax = OrderController.CalculateTax(state, currentOrder.CalculateSubTotal());

            return dTax;
        }

        // sets Control.Enable = false for child textbox controls
        protected void DisableTextBoxEdit(Control control)
        {
            foreach (Control ctrl in control.Controls)
            {
                if (ctrl is TextBox)
                {
                    ((TextBox)(ctrl)).Enabled = false;
                }
                if (ctrl is DropDownList)
                {
                    ((DropDownList)(ctrl)).Enabled = false;
                }
            }
        }

        public bool showModal()
        {
            // validate only for US addresses
            if (shipAddressEntry.SelectedAddress.Country == "US")
            {
                collection = validate.CheckAddress(shipAddressEntry.SelectedAddress);

                // only display the dialog if the quality ranking is below 0.9125
                if (collection[0].quality < Convert.ToDecimal(0.9125))
                {
                    RadioButtonList1.DataSource = collection;
                    RadioButtonList1.DataTextField = "returnDisplay";
                    RadioButtonList1.DataValueField = "rank";
                    RadioButtonList1.DataBind();

                    Panel1.Visible = true;
                    ModalPopupExtender1.Show();

                    return false;
                }
                else
                {
                    return true;
                }
            }
            else
            {
                return true;
            }

        }

        protected APIWrapper GetPPWrapper()
        {
            SiteConfig.Load();

            APIWrapper wrapper =
              new APIWrapper(SiteConfig.PayPalAPIAccountName
                    , SiteConfig.PayPalAPIAccountPassword
                    , SiteConfig.APIsignature
                    , (CurrencyCode)Enum.Parse(typeof(CurrencyCode),SiteConfig.defaultCurrencyCode)
                    , SiteConfig.APIIsLive);

            return wrapper;
        }

    #endregion

        #region PayPal Express Checkout

        protected void SetExpressCheckout()
        {
            try
            {
                // in case the user has entered an address
                SetProfile(Email.Text);

                // SetExpressCheckout
                APIWrapper wrapper = GetPPWrapper();

                // set email if we have one
                string sEmail = Email.Text;

                string successURL = Utility.GetPayPalExpressCheckoutSuccessUrl();
                string failURL = Utility.GetPayPalExpressCheckoutFailUrl();
                string sUrl = "";
                string ppToken = "";

                if (currentOrder.Items.Count > 0)
                {
                        ppToken = wrapper.SetExpressCheckout(sEmail, currentOrder.CalculateSubTotal(),
                          successURL, failURL, false, shipAddressEntry.SelectedAddress);

                    if (ppToken.ToLower().Contains("error"))
                    {
                        throw new Exception("PayPal has returned an error message: " + ppToken.ToString());
                    }
                    else
                    {
                        
                        sUrl = "https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=" + ppToken;

                        if (!SiteConfig.APIIsLive)
                        {
                        sUrl = "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=" + ppToken;
                        }

                        try
                        {
                            Response.Redirect(sUrl, false);
                        }
                        catch (Exception)
                        {
                            // ResultMessage1.ShowFail(x.Message);
                            throw;
                        }
                    }

                }
                else
                {
                    // send back to the cart page
                    Response.Redirect(Utility.GetCartUrl(), false);
                }

            }
            catch (Exception)
            {
                throw;
            }
        }

        protected void ProcessExpressReturn(string sToken)
        {
            try
            {
                //get the wrapper
                APIWrapper wrapper = GetPPWrapper();

                // back from the PayPal site
                Commerce.Common.Address payer = wrapper.GetExpressCheckout(sToken);

                // set the email and addresses
                Email.Text = payer.Email;
                billAddressEntry.SelectedAddress = payer;
                shipAddressEntry.SelectedAddress = payer;
                SaveAddresses();
                OrderController.SaveAddress(payer);

                //set the token in the ViewState 
                ViewState.Add("ppToken", payer.PayPalToken);
                ViewState.Add("ppID", payer.PayPalPayerID);

                //need to run the tax calc now that we have an address
                SetCurrentOrder();

                // PVS - 5/23/2008- change to use tax calc by state rather than ZIP
                USState state = (USState)Utility.StringToEnum(typeof(Commerce.Common.USState), payer.StateOrRegion);

                currentOrder.TaxAmount = OrderController.CalculateTax(state, currentOrder.CalculateSubTotal());

                //save down the order to the ViewState so that it can be picked up when Running the Charge
                SetOrderInfo();

            }
            catch (Exception)
            {
                throw;
            }
        }

        protected string RunExpressCheckout()
        {
            //this is the PayPal response holder
            string orderID = "";

            try
            {
            string sToken = Utility.GetParameter("token");
            
            SaveAddresses();
            SetOrderInfo();

            //run the Final Express Checkout
                Transaction trans = OrderController.TransactOrder(currentOrder, TransactionType.PayPalPayment);
                orderID = currentOrder.OrderGUID;

                return orderID;
            }
            catch (Exception)
            {
                throw;
            }

        }

        #endregion
    }
}